package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.annotation.annotation.cache.Cache;
import com.eastfair.annotation.annotation.cache.Magic;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.base.entity.SuperEntity;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.context.StaticContextUtil;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.database.mybatis.conditions.Wraps;
import com.eastfair.database.mybatis.conditions.query.QueryWrap;
import com.eastfair.messagecenter.api.MsgServiceFeign;
import com.eastfair.messagecenter.util.SendMsgUtil;
import com.eastfair.messagecenter.util.SmsSendDtoUtil;
import com.eastfair.venueservice.consts.CommonConstants;
import com.eastfair.venueservice.dao.DepositWarningMapper;
import com.eastfair.venueservice.dto.DepositWarningDTO;
import com.eastfair.venueservice.dto.DepositWarningQuery;
import com.eastfair.venueservice.entity.DepositWarning;
import com.eastfair.venueservice.entity.ExhibitionCompany;
import com.eastfair.venueservice.entity.ExhibitionManage;
import com.eastfair.venueservice.entity.ServiceOrder;
import com.eastfair.venueservice.enumeration.DepositWarningWarningStandardEnum;
import com.eastfair.venueservice.enumeration.DepositWarningWarningStandardJudgeEnum;
import com.eastfair.venueservice.service.DepositWarningService;
import com.eastfair.venueservice.service.ExhibitionCompanyService;
import com.eastfair.venueservice.service.ExhibitionManageService;
import com.eastfair.venueservice.service.ServiceBookingService;
import com.eastfair.venueservice.vo.DepositWarningVO;
import com.eastfair.venueservice.vo.ExhibitionCompanyVO;
import com.eastfair.venueservice.vo.ServiceBookingVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 业务实现类
 * 押金预警
 * </p>
 *
 * @author linan
 * @date 2023-02-14
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class DepositWarningServiceImpl extends SuperServiceImpl<DepositWarningMapper, DepositWarning> implements DepositWarningService {

    @Resource
    private ExhibitionCompanyService exhibitionCompanyService;
    @Resource
    private ServiceBookingService serviceBookingService;
    @Resource
    private MsgServiceFeign msgServiceFeign;
    @Resource
    private ExhibitionManageService exhibitionManageService;
    @Resource
    private SendMsgUtil sendMsgUtil;

    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;


    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<DepositWarning> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }

    /**
     * 通用查询
     *
     * @param modelDTO DTO
     * @param ids      主键id集合
     * @return list
     */
    @Override
    public List<DepositWarning> list(DepositWarningDTO modelDTO, List<Long> ids) {
        return ((DepositWarningService) AopContext.currentProxy()).listOfCache(modelDTO, ids);
    }


    @Override
    protected R<Boolean> handlerSave(DepositWarning model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    /**
     * 缓存查询
     *
     * @param modelDTO DTO
     * @param ids      主键id集合
     * @return list
     */
    @Override
    @Cache(key = "",
            magic = @Magic(
                    key = "{" +
                            "{'isEnabled', #args[0]?.isEnabled}," +
                            "{'createdName', #args[0]?.createdName}," +
                            "{'exhibitionManageId', #args[0]?.exhibitionManageId}," +
                            "{'exhibitionManageName', #args[0]?.exhibitionManageName}," +
                            "{'warningName', #args[0]?.warningName}," +
                            "{'serviceProviderType', #args[0]?.serviceProviderType}," +
                            "{'serviceProviderId', #args[0]?.serviceProviderId}," +
                            "{'serviceProviderName', #args[0]?.serviceProviderName}," +
                            "{'warningStandard', #args[0]?.warningStandard}," +
                            "{'warningStandardJudge', #args[0]?.warningStandardJudge}," +
                            "{'priceType', #args[0]?.priceType}," +
                            "{'price', #args[0]?.price}," +
                            "{'msgTempId', #args[0]?.msgTempId}," +
                            "{'emailTempId', #args[0]?.emailTempId}," +
                            "{'id', #args[1]}" +
                            "}"))
    public List<DepositWarning> listOfCache(DepositWarningDTO modelDTO, List<Long> ids) {
        //查询
        DepositWarning queryModel = new DepositWarning();
        if (modelDTO != null) {
            BeanUtils.copyProperties(modelDTO, queryModel);
        }
        QueryWrap<DepositWarning> wrapper = Wraps.q(queryModel);
        if (ids != null && !ids.isEmpty()) {
            wrapper.lambda().in(DepositWarning::getId, ids);
        }
        //添加其他业务查询条件
        wrapper.lambda().eq(DepositWarning::getIsDeleted, BusinessConstant.DELETE_NO);
        List<DepositWarning> modelList = list(wrapper);
        return modelList;
    }

    @Override
    public Page<DepositWarningVO> queryDepositWarning(PageParams<DepositWarningQuery> query) {
        Page<DepositWarning> buildPage = query.buildPage();
        DepositWarningQuery model = query.getModel();
        LambdaQueryWrapper<DepositWarning> wrapper = new QueryWrapper<DepositWarning>().lambda()
                .like(StringUtils.isNotBlank(model.getWarningName()), DepositWarning::getWarningName, model.getWarningName())
                .like(StringUtils.isNotBlank(model.getExhibitionManageName()), DepositWarning::getExhibitionManageName, model.getExhibitionManageName())
                .like(StringUtils.isNotBlank(model.getServiceProviderName()), DepositWarning::getServiceProviderName, model.getServiceProviderName())
                .ge(Objects.nonNull(model.getCreateTimeStart()), SuperEntity::getCreateTime, model.getCreateTimeStart())
                .le(Objects.nonNull(model.getCreateTimeEnd()), SuperEntity::getCreateTime, model.getCreateTimeEnd())
                .orderByDesc(SuperEntity::getCreateTime);
        Page<DepositWarning> page = page(buildPage, wrapper);
        return ConvertUtil.convertPage(page,DepositWarningVO.class);
    }

    @Override
    public Boolean updateDepositWarning(DepositWarningDTO dto) {
        DepositWarning updateEntity= BeanUtil.copyProperties(dto,DepositWarning.class);
        return updateById(updateEntity);
    }

    @Override
    public Boolean addDepositWarning(DepositWarningDTO dto) {
        DepositWarning entity = BeanUtil.copyProperties(dto, DepositWarning.class);
        return save(entity);
    }

    @Override
    public void warning(ServiceOrder serviceOrder) {
        // 查询该服务商、该展会下的预警配置
        threadPoolTaskExecutor.execute(() -> {
            Long exhibitionManageId = serviceOrder.getExhibitionManageId();
            Long companyId = serviceOrder.getCompanyId();
            // 短信提醒、站内信提醒
            warningDealMsg(companyId, exhibitionManageId);
        });
    }

    @Override
    public void warning(Long companyId, Long exhibitionManageId) {
        // 查询该服务商、该展会下的预警配置
        // 短信提醒、站内信提醒
        threadPoolTaskExecutor.execute(() -> warningDealMsg(companyId, exhibitionManageId));
    }

    @Override
    public void updateByExhibition(DepositWarningDTO depositWarningDTO) {
        update(new UpdateWrapper<DepositWarning>().lambda()
                .eq(DepositWarning::getIsDeleted,BusinessConstant.DELETE_NO)
                .eq(DepositWarning::getExhibitionManageId,depositWarningDTO.getExhibitionManageId())
                .eq(DepositWarning::getServiceProviderId,depositWarningDTO.getServiceProviderId())
                .set(DepositWarning::getServiceProviderId,depositWarningDTO.getServiceProviderId()));
    }

    private void warningDealMsg(Long companyId, Long exhibitionManageId) {
        ArrayList<Long> companyIds = new ArrayList<>();
        companyIds.add(companyId);
        Long providerId = null;
        ExhibitionCompany exhibitionCompany = exhibitionCompanyService.getById(companyId);
        if(Objects.nonNull(exhibitionCompany)){
            providerId = exhibitionCompany.getServiceProviderId();
            companyIds.add(providerId);
        }
        List<DepositWarning> list = list(new QueryWrapper<DepositWarning>().lambda()
                .eq(DepositWarning::getIsEnabled, BusinessConstant.YES)
                .eq(DepositWarning::getIsDeleted, BusinessConstant.NO)
                .in(DepositWarning::getServiceProviderId, companyIds)
                .eq(DepositWarning::getExhibitionManageId, exhibitionManageId));
        ExhibitionManage exhibitionManage = exhibitionManageService.getById(exhibitionManageId);
        String exhibitionManageName = Objects.nonNull(exhibitionManage)?exhibitionManage.getExhibitionName(): Strings.EMPTY;
        for (DepositWarning depositWarning : list) {
            Long serviceProviderId = depositWarning.getServiceProviderId();
            // 查询exhibitionCompany
            ExhibitionCompanyVO voByServiceProviderId = exhibitionCompanyService.getVOByServiceProviderId(companyId, exhibitionManageId);
            String providerType = null;
            if(Objects.isNull(voByServiceProviderId)){
                voByServiceProviderId = exhibitionCompanyService.getVOByServiceProviderId(providerId, exhibitionManageId);
            }
            // 短信发送的手机号
            String phone = null;
            String companyName = null;
            // 公司名称
            List<Long> ids = new ArrayList<>();
            ids.add(serviceProviderId);
            if(Objects.nonNull(voByServiceProviderId)){
                ids.add(voByServiceProviderId.getId());
                phone = voByServiceProviderId.getPhone();
                companyName = voByServiceProviderId.getCompanyName();
                providerType = voByServiceProviderId.getCompanyType().getDesc().substring(0,2);
            }
            // 查询所有预定的各项服务总金额
            List<ServiceBookingVO> serviceBookingAmount = serviceBookingService.queryServiceItemAmount(ids, exhibitionManageId);
            DepositWarningWarningStandardEnum warningStandard = depositWarning.getWarningStandard();
            BigDecimal price = depositWarning.getPrice();
            DepositWarningWarningStandardJudgeEnum warningStandardJudge = depositWarning.getWarningStandardJudge();
            // 告警集合
            if (StringUtils.isNotBlank(phone)) {
                Set<String> nums = new HashSet<>();
                nums.add(phone);
                judgeDeal(exhibitionManageName, providerType, companyName, serviceBookingAmount, warningStandard, price, warningStandardJudge, nums);
            }
        }
    }

    private void judgeDeal(String exhibitionManageName, String providerType, String companyName, List<ServiceBookingVO> serviceBookingAmount, DepositWarningWarningStandardEnum warningStandard, BigDecimal price, DepositWarningWarningStandardJudgeEnum warningStandardJudge, Set<String> nums) {
        if (warningStandard.eq(DepositWarningWarningStandardEnum.SIMPLE_SERVICE_AMOUNT)) {
            // 单项服务预警
            for (ServiceBookingVO serviceBookingVO : serviceBookingAmount) {
                BigDecimal unitPriceAfterDiscount = serviceBookingVO.getUnitPriceAfterDiscount();
                int compare = unitPriceAfterDiscount.compareTo(price);
                if (warningStandardJudge.eq(DepositWarningWarningStandardJudgeEnum.EQUAL) && compare == 0) {
                    // 等于的情况
                    msgServiceFeign.sendSmsMsg(SmsSendDtoUtil.sendSmsDto(CommonConstants.BUSINESS_COMMON, nums, String.format("%s累计预定的%s服务总额已等于%s元，请联系相关人员及时处理。", companyName, serviceBookingVO.getServiceName(), price)));
                    String content=String.format("%s，%s：%s累计预订的服务%s总额等于%s，请及时处理！", exhibitionManageName, providerType, companyName, serviceBookingVO.getServiceName(), price.toString());
                    log.info(content);
                    sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
                } else if (warningStandardJudge.eq(DepositWarningWarningStandardJudgeEnum.GREATER_THAN) && compare > 0) {
                    // 大于的情况
                    msgServiceFeign.sendSmsMsg(SmsSendDtoUtil.sendSmsDto(CommonConstants.BUSINESS_COMMON, nums, String.format("%s累计预定的%s服务总额已大于%s元，请联系相关人员及时处理。", companyName, serviceBookingVO.getServiceName(), price)));
                    String content=String.format("%s，%s：%s累计预订的服务%s总额大于%s，请及时处理！", exhibitionManageName, providerType, companyName, serviceBookingVO.getServiceName(), price.toString());
                    log.info(content);
                    sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
                } else if (warningStandardJudge.eq(DepositWarningWarningStandardJudgeEnum.GREATER_THAN_OR_EQUAL) && compare >= 0) {
                    // 大于等于的情况
                    msgServiceFeign.sendSmsMsg(SmsSendDtoUtil.sendSmsDto(CommonConstants.BUSINESS_COMMON, nums, String.format("%s累计预定的%s服务总额已大于等于%s元，请联系相关人员及时处理。", companyName, serviceBookingVO.getServiceName(), price)));
                    String content=String.format("%s，%s：%s累计预订的服务%s总额大于等于%s，请及时处理！", exhibitionManageName, providerType, companyName, serviceBookingVO.getServiceName(), price.toString());
                    log.info(content);
                    sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
                }
            }
        } else {
            // 总服务金额预计
            BigDecimal reduce = serviceBookingAmount.stream().map(ServiceBookingVO::getUnitPriceAfterDiscount).reduce(BigDecimal.ZERO, BigDecimal::add);
            int compare = reduce.compareTo(price);
            if (warningStandardJudge.eq(DepositWarningWarningStandardJudgeEnum.EQUAL) && compare == 0) {
                // 等于的情况
                msgServiceFeign.sendSmsMsg(SmsSendDtoUtil.sendSmsDto(CommonConstants.BUSINESS_COMMON, nums, String.format("%s累计预定的服务总额已等于%s元，请联系相关人员及时处理。", companyName, price)));
                String content=String.format("%s，%s：%s累计预订的服务总额等于%s，请及时处理！", exhibitionManageName, providerType, companyName,  price.toString());
                log.info(content);
                sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
            } else if (warningStandardJudge.eq(DepositWarningWarningStandardJudgeEnum.GREATER_THAN) && compare > 0) {
                // 大于的情况
                msgServiceFeign.sendSmsMsg(SmsSendDtoUtil.sendSmsDto(CommonConstants.BUSINESS_COMMON, nums, String.format("%s累计预定的服务总额已大于%s元，请联系相关人员及时处理。", companyName, price)));
                String content=String.format("%s，%s：%s累计预订的服务总额大于%s，请及时处理！", exhibitionManageName, providerType, companyName,  price.toString());
                log.info(content);
                sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
            } else if (warningStandardJudge.eq(DepositWarningWarningStandardJudgeEnum.GREATER_THAN_OR_EQUAL) && compare >= 0) {
                // 大于等于的情况
                msgServiceFeign.sendSmsMsg(SmsSendDtoUtil.sendSmsDto(CommonConstants.BUSINESS_COMMON, nums, String.format("%s累计预定的服务总额已大于等于%s元，请联系相关人员及时处理。", companyName, price)));
                String content=String.format("%s，%s：%s累计预订的服务总额大于等于%s，请及时处理！", exhibitionManageName, providerType, companyName,  price.toString());
                log.info(content);
                sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
            }
        }
    }

    /**
     * do转vo
     *
     * @param model model
     * @return modelVo
     */
    @Override
    public DepositWarningVO doToVo(DepositWarning model) {
        DepositWarningVO modelVo = new DepositWarningVO();
        BeanUtils.copyProperties(model, modelVo);
        modelVo.setId(model.getId());
        return modelVo;
    }

    /**
     * do转vo
     *
     * @param modelList modelList
     * @return list
     */
    @Override
    public List<DepositWarningVO> doToVos(List<DepositWarning> modelList) {
        if (modelList == null || modelList.isEmpty()) {
            return null;
        }
        List<DepositWarningVO> result = new ArrayList<>();
        for (DepositWarning model : modelList) {
            result.add(doToVo(model));
        }
        return result;
    }
}
